/**
 * 
 */
package com.zufangbao.earth.web.controller.order;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.Result;
import com.demo2do.core.persistence.support.Filter;
import com.demo2do.core.utils.DateUtils;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.utils.StringUtils;
import com.demo2do.core.web.interceptor.InfoMessage;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.resolver.Page;
import com.demo2do.core.web.resolver.Secure;
import com.zufangbao.earth.entity.security.Principal;
import com.zufangbao.sun.entity.Channel;
import com.zufangbao.sun.entity.account.Account;
import com.zufangbao.sun.entity.company.corp.App;
import com.zufangbao.sun.entity.finance.FinancePaymentRecord;
import com.zufangbao.sun.entity.icbc.business.ReceiveOrderMap;
import com.zufangbao.sun.entity.order.Order;
import com.zufangbao.sun.entity.order.OrderStatus;
import com.zufangbao.sun.entity.order.RepaymentType;
import com.zufangbao.sun.entity.order.TransactionRecord;
import com.zufangbao.sun.service.AppService;
import com.zufangbao.sun.service.ContractService;
import com.zufangbao.sun.service.DeductService;
import com.zufangbao.sun.service.FinancePaymentRecordService;
import com.zufangbao.sun.service.OrderService;
import com.zufangbao.sun.service.PayService;
import com.zufangbao.sun.service.ReceiveOrderMapService;
import com.zufangbao.sun.service.TransactionRecordService;

/**
 * @author Downpour
 */
@Controller
@RequestMapping("/orders")
@MenuSetting("menu-order")
public class OrderController {

	private static final long YOPARK_APP_ID = 2L;
	@Autowired
	private OrderService orderService;
	@Autowired
	private TransactionRecordService transactionRecordService;
	@Autowired
	private FinancePaymentRecordService financePaymentRecordService;
	@Autowired
	private DeductService deductService;
	@Autowired
	private PayService payService;
	@Autowired
	private AppService appService;
	@Autowired
	private ContractService contractService;
	@Autowired
	private ReceiveOrderMapService receiveOrderMapService;

	/**
	 * List paid orders
	 * 
	 * @return
	 */
	@Deprecated
	@RequestMapping(value = { "/current" })
	@MenuSetting("submenu-order-current")
	public ModelAndView listPaid(Page page) {

		page.setEveryPage(50);

		Filter filter = new Filter().addLessThan("startDate", new Date())
				.addGreaterThan("endDate", new Date());

		List<Order> orderList = orderService.list(Order.class, filter, page);

		ModelAndView modelAndView = new ModelAndView("order/order-current-list");
		modelAndView.addObject("orderList", orderList);

		return modelAndView;
	}

	/**
	 * List unpaid orders
	 * 
	 * @return
	 */
	@RequestMapping(value = { "", "/all" })
	@MenuSetting("submenu-order-all")
	public ModelAndView listUnpaid(Page page) {

		com.demo2do.core.persistence.support.Order orderByDueDate = new com.demo2do.core.persistence.support.Order();
		orderByDueDate.add("due_date", "ASC");
		List<Order> orderList = orderService.list(Order.class, orderByDueDate,
				page);

		ModelAndView modelAndView = new ModelAndView("order/order-all-list");
		modelAndView.addObject("orderList", orderList);

		return modelAndView;
	}

	/**
	 * List order current detail
	 * 
	 * @return
	 */
	@RequestMapping("/current/{orderId}/detail")
	@MenuSetting("submenu-order-current")
	public ModelAndView orderCurrentDetail(@PathVariable("orderId") Long orderId) {

		Order order = orderService.load(Order.class, orderId);
		List<TransactionRecord> transactionRecords = transactionRecordService
				.getTransactionListByOrder(order);
		List<FinancePaymentRecord> financePaymentRecords = financePaymentRecordService
				.getFinancePaymentRecordListByOrder(order);
		List<ReceiveOrderMap> mapList = receiveOrderMapService
				.getReceiveOrderMapByOrder(order);

		ModelAndView modelAndView = new ModelAndView("order/order-detail");
		modelAndView.addObject("order", order);
		modelAndView.addObject("transactionRecords", transactionRecords);
		modelAndView.addObject("financePaymentRecords", financePaymentRecords);
		modelAndView.addObject("isDirectBank", Channel.DIRECTBANK
				.equals(orderService.getOrderChannel(orderId)));
		modelAndView.addObject("mapList", mapList);

		return modelAndView;
	}

	/**
	 * List order all detail
	 * 
	 * @return
	 */
	@RequestMapping("/all/{orderId}/detail")
	@MenuSetting("submenu-order-all")
	public ModelAndView orderAllDetail(@PathVariable("orderId") Long orderId) {

		Order order = orderService.load(Order.class, orderId);
		List<TransactionRecord> transactionRecords = transactionRecordService
				.getTransactionListByOrder(order);
		List<FinancePaymentRecord> financePaymentRecords = financePaymentRecordService
				.getFinancePaymentRecordListByOrder(order);
		List<ReceiveOrderMap> mapList = receiveOrderMapService
				.getReceiveOrderMapByOrder(order);

		ModelAndView modelAndView = new ModelAndView("order/order-detail");
		modelAndView.addObject("order", order);
		modelAndView.addObject("transactionRecords", transactionRecords);
		modelAndView.addObject("financePaymentRecords", financePaymentRecords);
		modelAndView.addObject("isDirectBank", Channel.DIRECTBANK
				.equals(orderService.getOrderChannel(orderId)));
		modelAndView.addObject("mapList", mapList);

		return modelAndView;
	}

	/**
	 * to deduct page
	 * 
	 * @param orderId
	 * @return
	 */
	@RequestMapping("/all/{orderId}/deduct")
	public ModelAndView deduct(@PathVariable("orderId") Long orderId) {
		ModelAndView modelAndView = new ModelAndView("order/order-deduct");

		Order order = orderService.load(Order.class, orderId);

		/*
		 * List<AppArriveRecord> arriveRecords = deductService
		 * .getArriveRecordsByOrderId(orderId);
		 */

		/*
		 * AppArriveRecord defaultArriveRecord =
		 * orderService.getDefaultArriveRecord(orderId); if(defaultArriveRecord
		 * == null){ modelAndView.addObject("defaultArriveRecordId", -1); }else{
		 * modelAndView.addObject("defaultArriveRecordId",
		 * defaultArriveRecord.getId()); }
		 */

		// modelAndView.addObject("arriveRecords", arriveRecords);
		modelAndView.addObject("order", order);
		return modelAndView;
	}
	
	@RequestMapping("/all/{orderId}/bufferDeduct")
	public ModelAndView bufferDeduct(@PathVariable("orderId") Long orderId) {
		ModelAndView modelAndView = new ModelAndView("order/order-buffer-deduct");

		Order order = orderService.load(Order.class, orderId);

		modelAndView.addObject("order", order);
		return modelAndView;
	}

	/**
	 * execute dedute
	 * 
	 * @param orderId
	 * @param appArriveRecordId
	 * @param deductAmount
	 * @param remark
	 * @return
	 */
	@RequestMapping(value = "/detail/doDeduct", method = RequestMethod.POST)
	public @ResponseBody String doDeduct(@RequestParam("orderId") Long orderId,
			@RequestParam("deductAmount") String deductAmount,
			@RequestParam("remark") String remark, @Secure Principal principal) {
		Result result = deductService.manualDeduct(orderId, new BigDecimal(
				deductAmount), remark, principal.getId());

		return JsonUtils.toJsonString(result);
	}
	
	
	@RequestMapping(value = "/detail/doBufferDeduct", method = RequestMethod.POST)
	public @ResponseBody String doBufferDeduct(@RequestParam("orderId") Long orderId,
			@RequestParam("deductAmount") String deductAmount,
			@RequestParam("remark") String remark, @Secure Principal principal) {
		Result result = deductService.manualBufferDeduct(orderId, new BigDecimal(
				deductAmount), remark, principal.getId());

		return JsonUtils.toJsonString(result);
	}

	/**
	 * to pay page
	 * 
	 * @param orderId
	 * @return
	 */
	@RequestMapping("/all/{orderId}/pay")
	public ModelAndView pay(@PathVariable("orderId") Long orderId) {
		ModelAndView modelAndView = new ModelAndView("order/order-pay");

		Order order = orderService.load(Order.class, orderId);
		Account account = payService.getRePayAccountInfo(order);

		modelAndView.addObject("order", order);
		modelAndView.addObject("account", account);
		modelAndView.addObject("RepaymentType", RepaymentType.values());
		return modelAndView;
	}

	/**
	 * execute pay
	 * 
	 * @param orderId
	 * @param accountNo
	 * @param accountName
	 * @param payAmount
	 * @param remark
	 * @return
	 */
	@RequestMapping(value = "/detail/doPay", method = RequestMethod.POST)
	public @ResponseBody String doPay(@RequestParam("orderId") Long orderId,
			@RequestParam("accountNo") String accountNo,
			@RequestParam("accountName") String accountName,
			@RequestParam("payAmount") String payAmount,
			@RequestParam("remark") String remark, @Secure Principal principal) {

		Result result = payService.manualPay(orderId, accountNo, accountName,
				new BigDecimal(payAmount), remark, principal.getId());

		return JsonUtils.toJsonString(result);
	}

	/**
	 * 
	 * @return
	 */
	@RequestMapping("current/search")
	public ModelAndView searchCurrent() {
		ModelAndView modelAndView = new ModelAndView(
				"order/order-current-search");
		modelAndView.addObject("OrderStatus", OrderStatus.values());
		return modelAndView;
	}

	/**
	 * 当期订单查询
	 * 
	 * @param request
	 * @param contractNo
	 * @param customerName
	 * @param page
	 * @return
	 */
	@RequestMapping(value = "current/search", method = RequestMethod.GET, params = "filter")
	@MenuSetting("submenu-order-current")
	public ModelAndView onSearchCurrent(
			HttpServletRequest request,
			@RequestParam(value = "contractNo", required = false) String contractNo,
			@RequestParam(value = "orderNo", required = false) String orderNo,
			@RequestParam(value = "orderStatus", required = false) String orderStatus,
			Page page) {

		ModelAndView modelAndView = new ModelAndView("order/order-current-list");

		Filter filter = new Filter().addLessThan("startDate", new Date())
				.addGreaterThan("endDate", new Date());

		if (!orderNo.isEmpty()) {
			filter.addEquals("orderNo", orderNo);
		}

		if (!contractNo.isEmpty()) {
			filter.addEquals("contract.contractNo", contractNo);
		}

		if (!orderStatus.isEmpty()) {
			filter.addEquals("orderStatus",
					OrderStatus.fromValue(Integer.parseInt(orderStatus)));
		}

		List<Order> orderList = orderService.list(Order.class, filter, page);

		String queryString = request.getQueryString();
		Map<String, String> queries = StringUtils.parseQueryString(queryString);
		if (queries.containsKey("page")) {
			queries.remove("page");
		}

		modelAndView.addObject("orderList", orderList);
		modelAndView.addObject("queryString",
				StringUtils.toQueryString(queries));

		return modelAndView;
	}

	/**
	 * 
	 * @return
	 */
	@RequestMapping("all/search")
	public ModelAndView searchAll() {
		ModelAndView modelAndView = new ModelAndView("order/order-all-search");
		List<App> appList = appService.loadAll(App.class);
		modelAndView.addObject("appList", appList);
		modelAndView.addObject("OrderStatus", OrderStatus.values());
		return modelAndView;
	}

	/**
	 * 所有订单查询
	 * 
	 * @param request
	 * @param contractNo
	 * @param customerName
	 * @param page
	 * @return
	 */
	@RequestMapping(value = { "all", "" }, method = RequestMethod.GET)
	@MenuSetting("submenu-order-all")
	public ModelAndView onSearchAll(
			@Secure Principal principal,
			HttpServletRequest request,
			@RequestParam(value = "contractNo", required = false) String contractNo,
			@RequestParam(value = "orderNo", required = false) String orderNo,
			@RequestParam(value = "orderStatus", required = false) String orderStatus,
			@RequestParam(value = "app", required = false) String app,
			@RequestParam(value = "startDate", required = false) String startDate,
			@RequestParam(value = "endDate", required = false) String endDate,
			Page page) {
		Filter filter = new Filter();
		List<App> appList = new ArrayList<App>();
		ModelAndView modelAndView = new ModelAndView("order/order-all-list");
		if (principal.getAuthority().equals("ROLE_APP")
				|| principal.getAuthority().equals("ROLE_BANK_APP")
				|| principal.getAuthority().equals("ROLE_MERCURY_APP")) {
			filter.addEquals("app.id", principal.getKeyId());
			App real_app = this.appService.load(App.class, principal.getKeyId());
			appList.add(real_app);
			modelAndView.addObject("app", principal.getKeyId());
		} else if (principal.getAuthority().equals("ROLE_SUPER_USER")) {
			appList = appService.loadAll(App.class);
		}
		if (!StringUtils.isEmpty(orderNo)) {
			filter.addLike("orderNo", orderNo);
		}
		if (!StringUtils.isEmpty(contractNo)) {
			filter.addLike("contract.contractNo", contractNo);
		}

		if (!StringUtils.isEmpty(orderStatus)) {
			filter.addEquals("orderStatus",
					OrderStatus.fromValue(Integer.parseInt(orderStatus)));
		}
		if (principal.getAuthority().equals("ROLE_SUPER_USER")&&!StringUtils.isEmpty(app)) {
			filter.addEquals("contract.app.id", Long.parseLong(app));
		}

		if (!StringUtils.isEmpty(startDate)) {
			filter.addGreaterThan("dueDate", calculate_pre_date(startDate));
		}

		if (!StringUtils.isEmpty(endDate)) {
			filter.addLessThan("dueDate", calculate_next_date(endDate));
		}

		com.demo2do.core.persistence.support.Order orderByDueDate = new com.demo2do.core.persistence.support.Order();
		orderByDueDate.add("due_date", "ASC");

		List<Order> orderList = orderService.list(Order.class, filter,
				orderByDueDate, page);

		modelAndView.addObject("appList", appList);
		modelAndView.addObject("OrderStatus", OrderStatus.values());
		modelAndView.addObject("orderList", orderList);
		modelAndView.addObject("orderNo", orderNo);
		modelAndView.addObject("contractNo", contractNo);
		modelAndView.addObject("orderStatus", orderStatus);
		modelAndView.addObject("app", app);
		modelAndView.addObject("startDate", startDate);
		modelAndView.addObject("endDate", endDate);

		String queryString = request.getQueryString();

		if (StringUtils.isEmpty(queryString)) {

			return modelAndView;
		}
		Map<String, String> queries = StringUtils.parseQueryString(queryString);
		queries.remove("page");

		modelAndView.addObject("queryString",
				StringUtils.toQueryString(queries));

		return modelAndView;
	}

	private Date calculate_next_date(String anchorDate) {
		return move_date_to_future(anchorDate, 1);
	}

	private Date move_date_to_future(String anchorDate, int days) {
		return DateUtils.addDays(DateUtils.parseDate(anchorDate, "yyyy-MM-dd"),
				days);
	}

	private Date calculate_pre_date(String anchorDate) {
		return move_date_to_future(anchorDate, -1);
	}

	/**
	 * List orders to confirm payment
	 * 
	 * @return
	 */
	@RequestMapping("/confirm")
	@MenuSetting("submenu-order-confirm")
	public ModelAndView listOrdersToConfirm(Page page) {
		List<Order> orderList = orderService.getOrdersToBeConfirmed();
		Date orderDueDay = DateUtils.addDays(DateUtils.parseDate(DateUtils.format(new Date()), "yyyy-MM-dd"), -11);
		List<Order> orderBufferingDeductList = orderService.getBufferingDeductOrderList(orderDueDay,YOPARK_APP_ID);
		ModelAndView modelAndView = new ModelAndView("order/order-confirm-list");
		modelAndView.addObject("orderList", orderList);
		modelAndView.addObject("orderBufferingDeductList", orderBufferingDeductList);
		return modelAndView;
	}

	@RequestMapping(value = "/detail/unbind", method = RequestMethod.POST)
	@MenuSetting("submenu-order-all")
	public @ResponseBody String unBind(
			@RequestParam("receiveOrderMapId") Long receiveOrderMapId) {
		Result result = new Result();
		if (receiveOrderMapService.unbindRelationship(receiveOrderMapId)) {
			result.success().message("解绑成功！");
		} else {
			result.fail().message("解绑失败!请稍后再试！");
		}
		return JsonUtils.toJsonString(result);
	}

	/**
	 * delete order
	 * 
	 * @param orderId
	 * @return
	 */
	@RequestMapping("/{orderId}/delete")
	public ModelAndView delete(@PathVariable("orderId") Long orderId) {

		ModelAndView modelAndView = new ModelAndView("order/order-delete");
		modelAndView.addObject("orderId", orderId);

		return modelAndView;
	}

	/**
	 * delete order
	 * 
	 * @return
	 */
//	@RequestMapping(value = "/{orderId}/delete", method = RequestMethod.POST)
//	public @ResponseBody String delete(@PathVariable("orderId") Long orderId,
//			@Secure Principal principal) {
//		
//		Result result = new Result();
//		Order order = orderService.load(Order.class, orderId);
//		
//		result = orderService.delete(orderId);
//
//		return JsonUtils.toJsonString(result);
//
//		//return "redirect:/contracts/" + order.getContract().getId() + "/detail";
//
//	}
	
}
